/**********************************************************************************************/
// dgt_ValentinaPlugin.cpp
//
// Valentina elements
// Copyright Diamant Group 2007
/**********************************************************************************************/
#include "dgt_ValentinaPlugin.h"
#include "dgt_Algorithm.h"

/**********************************************************************************************/
#ifdef _MANAGED
#pragma managed(push, off)
#endif

#ifndef dgt_KERNEL

/**********************************************************************************************/
BOOL APIENTRY DllMain( HMODULE hModule,
					  DWORD  ul_reason_for_call,
					  LPVOID lpReserved
					  )
{
	pInstance = new dgt_Valentina();

	return TRUE;
}

#endif


DGTEXPORT dgt_Plugin* GetPlugin( void )
{
	return pInstance;
}

/**********************************************************************************************/
/**********************************************************************************************/
dgt_Valentina::dgt_Valentina()
{
	InitValentina( 4 * 1024 * 1024 );
}

/**********************************************************************************************/
dgt_Valentina::~dgt_Valentina()
{
	Shutdown();
}

/**********************************************************************************************/
void dgt_Valentina::GetPluginInfo( dgt_PluginInfo& t_Info )
{
	t_Info.m_PluginName = _T("Valentina plugin");
	t_Info.m_PluginType = PLUGIN_STORE;
	t_Info.m_Description = _T("Plugin for storing Algorithm in Valentina database");
	t_Info.m_Version = _T("BETA");
}

/**********************************************************************************************/
dgt_Algorithm_Ptr dgt_Valentina::LoadAlgorithm( wxString inName )
{
	OpenDatabase( inName );

	wxString name;

	name = GetStringValue( MAIN_TABLE, _("Name"), 1 );

	// Fill input variables
	unsigned long rcount = GetRecCount( INVAR_TABLE );

	dgt_AlgVarArray tInpArray;

	for( unsigned i = 1; i<=rcount; i++ )
	{
		wxString name = GetStringValue( INVAR_TABLE, _("Name"), i );
		wxString lib = GetStringValue( INVAR_TABLE, _("Lib"), i );
		long code = GetLongValue( INVAR_TABLE, _("Code"), i );
		
		dgt_AlgVar_Ptr tVar( new dgt_AlgVar( name, lib, code ) );	

		tInpArray.Add( tVar );
	}

	// Fill internal variables
	rcount = GetRecCount( INTRVAR_TABLE );

	dgt_AlgVarArray tIntrArray;

	for( unsigned i = 1; i<=rcount; i++ )
	{
		wxString name = GetStringValue( INTRVAR_TABLE, _("Name"), i );
		wxString lib = GetStringValue( INTRVAR_TABLE, _("Lib"), i );
		long code = GetLongValue( INTRVAR_TABLE, _("Code"), i );

		dgt_AlgVar_Ptr tVar( new dgt_AlgVar( name, lib, code ) );	

		tIntrArray.Add( tVar );
	}

	// Fill output variables
	rcount = GetRecCount( OUTVAR_TABLE );

	dgt_AlgVarArray tOutArray;

	for( unsigned i = 1; i<=rcount; i++ )
	{
		wxString name = GetStringValue( OUTVAR_TABLE, _("Name"), i );
		wxString lib = GetStringValue( OUTVAR_TABLE, _("Lib"), i );
		long code = GetLongValue( OUTVAR_TABLE, _("Code"), i );

		dgt_AlgVar_Ptr tVar( new dgt_AlgVar( name, lib, code ) );	

		tOutArray.Add( tVar );
	}


	// Fill actions
	rcount = GetRecCount( ACT_TABLE );

	dgt_AlgActArray tActArray;

	for( unsigned i = 1; i<=rcount; i++ )
	{
		long block = GetLongValue( ACT_TABLE, _("Block"), i );
		wxString name = GetStringValue( ACT_TABLE, _("Name"), i );
		long code = GetLongValue( ACT_TABLE, _("Code"), i );
		wxArrayString args = ReconvertArgs( GetStringValue( ACT_TABLE, _("Args"), i ) );
		bool type = (bool) GetLongValue( ACT_TABLE, _("Type"), i );
		wxString lib = GetStringValue( ACT_TABLE, _("Lib"), i );
		long libcode = GetLongValue( ACT_TABLE, _("LibCode"), i );

		dgt_AlgAction_Ptr tAct( new dgt_AlgAction( block, name, code, args, type, lib, libcode ) );

		tActArray.Add( tAct );
	}

	// Fill condition
	rcount = GetRecCount( COND_TABLE );

	dgt_AlgCondArray tCondArray;

	for( unsigned i = 1; i<=rcount; i++ )
	{
		wxString name = GetStringValue( COND_TABLE, _("Func"), i );
		long code = GetLongValue( COND_TABLE, _("Code"), i );
		wxArrayString args = ReconvertArgs( GetStringValue( COND_TABLE, _("Args"), i ) );

		dgt_AlgCondition_Ptr tCond( new dgt_AlgCondition( name, code, args ) );

		tCondArray.Add( tCond );
	}

	// Fill logic jumps
	rcount = GetRecCount( JUMP_TABLE );

	dgt_AlgLogArray tLogArray;

	for( unsigned i = 1; i<=rcount; i++ )
	{
		long begin = GetLongValue( JUMP_TABLE, _("Start"), i );
		long end = GetLongValue( JUMP_TABLE, _("End"), i );
		wxArrayInt args = ReconvertIntArgs( GetStringValue( ACT_TABLE, _("Args"), i ) );
	
		dgt_AlgLogic_Ptr tLog( new dgt_AlgLogic( begin, end, args ) );

		tLogArray.Add( tLog );
	}

	CloseDatabase();

	dgt_Algorithm_Ptr tAlgorithm( new dgt_Algorithm( name, tActArray, tCondArray, tLogArray, tInpArray, tIntrArray, tOutArray ) );

	return tAlgorithm;
}

/**********************************************************************************************/
// Function for saving Algorithm
// inAlgorithm - Algorithm to save
// inName - output db
void dgt_Valentina::SaveAlgorithm(dgt_Algorithm_Ptr inAlgorithm, wxString inName )
{
	CreateDatabase( inName );
	OpenDatabase( inName );

	// Create tables
	CreateTable( MAIN_TABLE );
	CreateTable( INVAR_TABLE );
	CreateTable( INTRVAR_TABLE );
	CreateTable( OUTVAR_TABLE );
	CreateTable( ACT_TABLE );		// table for actions
	CreateTable( COND_TABLE );	// table for conditions
	CreateTable( JUMP_TABLE );		// table for logical jumps

	// Filling table of input vars
	CreateField( INVAR_TABLE, _T("Name"), STRING_FIELD );
	CreateField( INVAR_TABLE, _T("Lib"), STRING_FIELD );
	CreateField( INVAR_TABLE, _T("Code"), LONG_FIELD );

	dgt_AlgVarArray tInpArray = inAlgorithm->get_InputVars();

	for( unsigned long i = 0; i < tInpArray.Count(); i++ )
	{
		dgt_AlgVar_Ptr tVar = tInpArray.Item( i );

		SetBlank( INVAR_TABLE );
		SetValue( INVAR_TABLE, _T("Name"), tVar->get_Name() );
		SetValue( INVAR_TABLE, _T("Lib"), tVar->get_PlugName() );
		SetValue( INVAR_TABLE, _T("Code"), tVar->get_Code() );
		AddRecord( INVAR_TABLE );
	}

	// Filling table of internal vars
	CreateField( INTRVAR_TABLE, _T("Name"), STRING_FIELD );
	CreateField( INTRVAR_TABLE, _T("Lib"), STRING_FIELD );
	CreateField( INTRVAR_TABLE, _T("Code"), LONG_FIELD );

	tInpArray = inAlgorithm->get_InternalVars();

	for( unsigned long i = 0; i < tInpArray.Count(); i++ )
	{
		dgt_AlgVar_Ptr tVar = tInpArray.Item( i );

		SetBlank( INTRVAR_TABLE );
		SetValue( INTRVAR_TABLE, _T("Name"), tVar->get_Name() );
		SetValue( INTRVAR_TABLE, _T("Lib"), tVar->get_PlugName() );
		SetValue( INTRVAR_TABLE, _T("Code"), tVar->get_Code() );
		AddRecord( INTRVAR_TABLE );
	}

	// Filling table of output vars
	CreateField( OUTVAR_TABLE, _T("Name"), STRING_FIELD );
	CreateField( OUTVAR_TABLE, _T("Lib"), STRING_FIELD );
	CreateField( OUTVAR_TABLE, _T("Code"), LONG_FIELD );

	tInpArray = inAlgorithm->get_OutputVars();

	for( unsigned long i = 0; i < tInpArray.Count(); i++ )
	{
		dgt_AlgVar_Ptr tVar = tInpArray.Item( i );

		SetBlank( OUTVAR_TABLE );
		SetValue( OUTVAR_TABLE, _T("Name"), tVar->get_Name() );
		SetValue( OUTVAR_TABLE, _T("Lib"), tVar->get_PlugName() );
		SetValue( OUTVAR_TABLE, _T("Code"), tVar->get_Code() );
		AddRecord( OUTVAR_TABLE );
	}

	// Filling table of actions
	CreateField( ACT_TABLE, _T("Block"), LONG_FIELD );
	CreateField( ACT_TABLE, _T("Name"), STRING_FIELD );
	CreateField( ACT_TABLE, _T("Code"), LONG_FIELD );
	CreateField( ACT_TABLE, _T("Args"), STRING_FIELD );
	CreateField( ACT_TABLE, _T("Type"), LONG_FIELD );
	CreateField( ACT_TABLE, _T("Lib"), STRING_FIELD );
	CreateField( ACT_TABLE, _T("LibCode"), LONG_FIELD );

	dgt_AlgActArray tActArray = inAlgorithm->get_Actions();

	for( unsigned i = 0; i < tActArray.Count(); i++ )
	{
		dgt_AlgAction_Ptr tAct = tActArray.Item( i );

		SetBlank( ACT_TABLE );
		SetValue( ACT_TABLE, _T("Block"), tAct->get_Block() );
		SetValue( ACT_TABLE, _T("Name"),tAct->get_Result() );
		SetValue( ACT_TABLE, _T("Code"), tAct->get_OpCode() );
		SetValue( ACT_TABLE, _T("Args"), ConvertArgs( tAct->get_ArgList() ) );
		SetValue( ACT_TABLE, _T("Type"), tAct->get_OpAttr() );
		SetValue( ACT_TABLE, _T("Lib"), tAct->get_OpPlugName() );
		SetValue( ACT_TABLE, _T("LibCode"), tAct->get_OpElemCode() );
		AddRecord( ACT_TABLE );
	}

	// Filling table of conditions
	CreateField( COND_TABLE, _T("Func"), STRING_FIELD );
	CreateField( COND_TABLE, _T("Code"), LONG_FIELD );
	CreateField( COND_TABLE, _T("Args"), STRING_FIELD );

	dgt_AlgCondArray tCondArray = inAlgorithm->get_Conditions();

	for( unsigned i = 0; i < tCondArray.Count(); i++ )
	{
		dgt_AlgCondition_Ptr t_Cond = tCondArray.Item( i );
		
		SetBlank( COND_TABLE );
		SetValue( COND_TABLE, _T("Func"), t_Cond->get_Plugin() );
		SetValue( COND_TABLE, _T("Code"), t_Cond->get_Number() );
		SetValue( COND_TABLE, _T("Args"), ConvertArgs( t_Cond->get_Operands() ) );
		AddRecord( COND_TABLE );
	}

	// Filling table of logical jumps
	CreateField( JUMP_TABLE, _T("Start"), LONG_FIELD );
	CreateField( JUMP_TABLE, _T("End"), LONG_FIELD );
	CreateField( JUMP_TABLE, _T("Jump"), STRING_FIELD );

	dgt_AlgLogArray tLogArray = inAlgorithm->get_Logics();

	for( unsigned i = 0; i < tLogArray.Count(); i++ )
	{
			
		dgt_AlgLogic_Ptr t_Log = tLogArray.Item( i );

		SetBlank( JUMP_TABLE );
		SetValue( JUMP_TABLE, _T("Start"), t_Log->get_StartBlock() );
		SetValue( JUMP_TABLE, _T("End"), t_Log->get_FinBlock() );
		SetValue( JUMP_TABLE, _T("Jump"), ConvertArgs( t_Log->get_CondList() ) );
		AddRecord( JUMP_TABLE );
	}


	CloseDatabase();
}

/**********************************************************************************************/
// Convert args array to view arg0|arg1|...
wxString dgt_Valentina::ConvertArgs(wxArrayString inArray)
{
	wxString tArgs;
	for( unsigned long j = 0; j < inArray.Count(); j++ )
	{
		tArgs+=inArray.Item( j );
		tArgs+=_("|");
	}
	return tArgs;
}

/**********************************************************************************************/
// Convert long args array to view arg0|arg1|...
wxString dgt_Valentina::ConvertArgs(wxArrayInt inArray)
{
	wxString tArgs;
	for( unsigned long j = 0; j < inArray.Count(); j++ )
	{
		wxString tElement;
		tElement = wxString::Format( _("%d|"), inArray.Item( j ) );
		tArgs+=tElement;
	}
	return tArgs;
}

/**********************************************************************************************/
wxArrayString dgt_Valentina::ReconvertArgs(wxString inValue)
{
	wxArrayString	res;
	unsigned		numSym;

	do 
	{
		wxString tStr = inValue.BeforeFirst( '|' );
		numSym = inValue.Find( '|' );
		res.Add( tStr );

		if( tStr = inValue )
			break;

		inValue.Remove( 0, tStr.Length()+1 );
		
	} 
	while(1);

	return res;
}

/**********************************************************************************************/
wxArrayInt dgt_Valentina::ReconvertIntArgs(wxString inValue)
{
	wxArrayInt	res;
	unsigned	numSym;

	do 
	{
		wxString tStr = inValue.BeforeFirst( '|' );
		numSym = inValue.Find( '|' );
		long t;
		tStr.ToLong( &t );
		res.Add( t );

		if( tStr = inValue )
			break;

		inValue.Remove( 0, tStr.Length()+1 );

	} 
	while(1);

	return res;
}


/**********************************************************************************************/
#ifdef _MANAGED
#pragma managed(pop)
#endif
